package com.rockcent.service.impl;

import com.rockcent.common.common.BusinessException;
import com.rockcent.common.common.PageResult;
import com.rockcent.common.domain.enumclass.Whether;
import com.rockcent.common.utils.ExcelCreateUtils;
import com.rockcent.helper.IntegrationCashCouponHelper;
import com.rockcent.helper.SysMessageHelper;
import com.rockcent.mall.lib.constants.SysMessageConstants;
import com.rockcent.mall.lib.domain.IntegrationCashCouponWallet;
import com.rockcent.mall.lib.domain.IntegrationChannel;
import com.rockcent.mall.lib.domain.MallCashCoupon;
import com.rockcent.mall.lib.domain.MallFund;
import com.rockcent.mall.lib.dto.IntegrationCashCouponWalletDto;
import com.rockcent.mall.lib.dto.IntegrationChannelDto;
import com.rockcent.mall.lib.dto.IntegrationCouponDetailRespDto;
import com.rockcent.mall.lib.dto.IntegrationCouponRespDto;
import com.rockcent.mall.lib.repository.IntegrationCashCouponWalletRepository;
import com.rockcent.mall.lib.repository.MallCashCouponRepository;
import com.rockcent.mall.lib.repository.MallFundRepository;
import com.rockcent.service.IntegrationCashCouponWalletSrv;
import com.rockcent.service.IntegrationChannelSrv;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 积分现金券
 * Created by zhangjh on 2016/12/14.
 */
@Service
public class IntegrationCashCouponWalletSrvImpl implements IntegrationCashCouponWalletSrv {

    private final Logger log = LoggerFactory.getLogger(IntegrationCashCouponWalletSrvImpl.class);

    @Autowired
    private MallFundRepository mallFundRepository;

    static Map<String, String> titleMap = new HashMap<>();

    static {
        titleMap.put("flagCode", "卡券标识码");
        titleMap.put("name", "现金券名称");
        titleMap.put("faceValue", "面值");
        titleMap.put("exchangeDate", "兑换时间");
        titleMap.put("receiveDate", "领取时间");
        titleMap.put("batchPutNo", "编号");
    }

    /**
     *
     */
    @Autowired
    private IntegrationCashCouponWalletRepository integrationCashWalletCouponRepository;

    @Autowired
    private IntegrationChannelSrv integrationChannelSrv;

    @Autowired
    private MallCashCouponRepository mallCashCouponRepository;

    /**
     * @param useNum
     * @param customerId
     * @param pageResult
     * @return
     */
    @Override
    public PageResult<IntegrationCashCouponWallet> queryCashWalletList(Long useNum, Long customerId, PageResult pageResult) {
        return integrationCashWalletCouponRepository.queryCashWalletListByUseNumAndCustomerId(useNum, customerId, pageResult);
    }

    /**
     * @param useNum
     * @param customerId
     * @return
     */
    @Override
    public Long queryCashWalletCount(Long useNum, Long customerId) {
        return integrationCashWalletCouponRepository.queryCashWalletCount(useNum, customerId);
    }

    /**
     * @param exchangeCode
     * @param exchangeNum
     * @param receiveNum
     * @param useNum
     * @return
     */
    @Override
    public IntegrationCashCouponWallet findByExchangeCodeAndExchangeNumAndReceiveNumAndUseNum(String exchangeCode, long exchangeNum, long receiveNum, long useNum) {
        return integrationCashWalletCouponRepository.findByExchangeCodeAndExchangeNumAndReceiveNumAndUseNum(exchangeCode, exchangeNum, receiveNum, useNum);
    }

    /**
     * @param integrationCashCouponWallet
     * @return
     */
    @Override
    public IntegrationCashCouponWallet save(IntegrationCashCouponWallet integrationCashCouponWallet) {
        return integrationCashWalletCouponRepository.save(integrationCashCouponWallet);
    }

    /**
     * @param mallCashCoupon
     */
    @Override
    public void save(MallCashCoupon mallCashCoupon) {
        Long count = mallCashCoupon.getQuantity();
//        List<String> codeList = IntegrationCashCouponHelper.SINGLETNONE.getExchangeCode("cash", count);
        Map<String, String> map = IntegrationCashCouponHelper.SINGLETNONE.getExchangeCodeAndFlagCode("cash", count);

        BigDecimal faceValue = mallCashCoupon.getFaceValue();
        Long mallId = mallCashCoupon.getMallId();
        Long cashCouponId = mallCashCoupon.getId();
        Long channelId = mallCashCoupon.getIntegrationChannelId();
        Long batchPutNo = mallCashCoupon.getBatchPutNo();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            IntegrationCashCouponWallet wallet = new IntegrationCashCouponWallet();
            wallet.setFaceValue(faceValue);
            wallet.setMallId(mallId);
            wallet.setExchangeCode(entry.getKey());
            wallet.setFlagCode(entry.getValue());
            wallet.setReceiveNum(0l);
            wallet.setExchangeNum(0l);
            wallet.setUseNum(0l);
            wallet.setCashCouponId(cashCouponId);
            wallet.setIntegrationChannelId(channelId);
            wallet.setBatchPutNo(batchPutNo);
            integrationCashWalletCouponRepository.save(wallet);
        }

//        for (String code : codeList) {
//            IntegrationCashCouponWallet wallet = new IntegrationCashCouponWallet();
//            wallet.setFaceValue(faceValue);
//            wallet.setMallId(mallId);
//            wallet.setExchangeCode(code);
//            wallet.setReceiveNum(0l);
//            wallet.setExchangeNum(0l);
//            wallet.setUseNum(0l);
//            wallet.setCashCouponId(cashCouponId);
//            integrationCashWalletCouponRepository.save(wallet);
//        }
    }

    /**
     * @param discountAmount
     * @param userId
     * @param mallId
     * @return
     */
    @Override
    public IntegrationCashCouponWallet getCloseToCashCoupon(BigDecimal discountAmount, Long userId, Long mallId) {
        return integrationCashWalletCouponRepository.getCloseToCashCoupon(discountAmount, userId, mallId);
    }

    /**
     * @param mallCashCoupon
     * @param mallId
     */
    @Override
    public void update(MallCashCoupon mallCashCoupon, Long mallId) {
        Long cashCouponId = mallCashCoupon.getId();
        Long integrationChannelId = mallCashCoupon.getIntegrationChannelId();
        Long batchPutNo = mallCashCoupon.getBatchPutNo();
        integrationCashWalletCouponRepository.updateIntegrationChannelId(cashCouponId, integrationChannelId, mallId, batchPutNo);
    }

    /**
     * @param mallCashCoupon
     * @param mallId
     */
    @Override
    public void stop(MallCashCoupon mallCashCoupon, Long mallId) {
        Long cashCouponId = mallCashCoupon.getId();
        integrationCashWalletCouponRepository.deleteByCashCouponId(cashCouponId, mallId);
    }

    /**
     * @param cashCouponId
     * @param integrationChannelId
     * @param mallId
     * @return
     */
    @Override
    public IntegrationCashCouponWallet caculateCash(Long cashCouponId, Long integrationChannelId, Long mallId) {
        return integrationCashWalletCouponRepository.caculateCash(cashCouponId, integrationChannelId, mallId);
    }

    /**
     * @param dto
     * @param mallId
     * @param whether
     * @param page
     * @return
     */
    @Override
    public PageResult<IntegrationCashCouponWalletDto> findChannelCashDetail(IntegrationChannelDto dto, Long mallId, Whether whether, PageResult page) {
        return integrationCashWalletCouponRepository.findChannelCashDetail(dto, mallId, whether, page);
    }

    /**
     * @param dto
     * @param mallId
     * @param whether
     * @return
     */
    @Override
    public Long qrExchangeNumByChannelId(IntegrationChannelDto dto, Long mallId, Whether whether) {
        return integrationCashWalletCouponRepository.qrExchangeNumByChannelId(dto, mallId, whether);
    }

    /**
     * @param request
     * @param response
     * @param dto
     * @param mallId
     * @param no
     * @throws IOException
     * @throws InvalidFormatException
     */
    @Override
    public void exportExchangeCash(HttpServletRequest request, HttpServletResponse response, IntegrationChannelDto dto, Long mallId, Whether no) throws IOException, InvalidFormatException {
//        PageResult page = this.getPage(dto.getPageNo(), Integer.MAX_VALUE);
        PageResult page = new PageResult(0, Integer.MAX_VALUE);//new PageResult(1, Integer.MAX_VALUE);
        PageResult<IntegrationCashCouponWalletDto> pageResult = findChannelCashDetail(dto, mallId, Whether.NO, page);
        Long total = 0l;//qrExchangeNumByChannelId(dto, mallId, Whether.NO);
        List<IntegrationCashCouponWalletDto> items = pageResult.data;
        if (null == items || items.isEmpty()) {
            items = new ArrayList<>();
        }
        total = Long.valueOf(items.size());
        IntegrationChannel integrationChannel = integrationChannelSrv.findOne(dto.getId());
        if (null == integrationChannel) {
            throw new BusinessException("渠道信息不正确");
        }
        MallFund mallFund = mallFundRepository.findByMallId(mallId);
//        BigDecimal availableAmount = mallFund.getAvailableCashAmount();
        Double exchangeNumCashAmount = qrExchangeNumCashAmountByChannelId(dto, mallId, Whether.NO);

        List<String> titles = dto.getTitles();
        List names = new ArrayList();
        for (String title : titles) {
            String name = titleMap.get(title);
            names.add(name);
        }

        Map<String, Object> data = new HashMap<>();
        String fileName = integrationChannel.getName();
        data.put("total", total == null ? 0 : total);
        data.put("name", fileName);
        data.put("typeName", "现金券");
        data.put("data", items);
        data.put("headers", names);
        data.put("availableAmount", String.valueOf(exchangeNumCashAmount));
        String dataName = "data";
        String objectProps = StringUtils.join(titles, ",");
        ExcelCreateUtils.getInstance().createDynamic(data, dataName, fileName + SUFFIX_XLSX, response, RESOURCE_PATH_INTEGRATION_CHANNEL_CASH_DETAIL_DYNAMIC, objectProps);
    }


    /**
     * @param channelId
     * @return
     */
    @Override
    public List<IntegrationCouponRespDto> queryList(Long channelId) {
        return integrationCashWalletCouponRepository.queryList(channelId);
    }


    /**
     * @param exchangeCode
     * @return
     */
    @Override
    public IntegrationCashCouponWallet findByExchangeCode(String exchangeCode) {
        return integrationCashWalletCouponRepository.findByExchangeCode(exchangeCode);
    }

    /**
     * @param exchangeCode
     * @param channelId
     * @param no
     * @param exchangeNum
     * @return
     */
    @Override
    public IntegrationCashCouponWallet findByExchangeCodeAndIntegrationChannelIdAndIsDeleteAndExchangeNum(String exchangeCode, long channelId, Whether no, long exchangeNum) {
        return integrationCashWalletCouponRepository.findByExchangeCodeAndIntegrationChannelIdAndIsDeleteAndExchangeNum(exchangeCode, channelId, Whether.NO, 0l);
    }

    /**
     * @param exchangeNum
     * @param cashCouponId
     * @param mallId
     * @param whether
     * @return
     */
    @Override
    public Long countByExchangeNumAndCashCouponIdAndMallIdAndIsDelete(Long exchangeNum, Long cashCouponId, Long mallId, Whether whether) {
        return integrationCashWalletCouponRepository.countByExchangeNumAndCashCouponIdAndMallIdAndIsDelete(exchangeNum, cashCouponId, mallId, whether);
    }

    /**
     * @param dto
     * @param mallId
     * @param no
     * @return
     */
    @Override
    public Double qrExchangeNumCashAmountByChannelId(IntegrationChannelDto dto, Long mallId, Whether no) {
        return integrationCashWalletCouponRepository.qrExchangeNumCashAmountByChannelId(dto, mallId, no);
    }

    /**
     * @param cashCouponId
     * @return
     */
    @Override
    public List<IntegrationCouponDetailRespDto> findByCashCounponId(Long cashCouponId) {
        return integrationCashWalletCouponRepository.findByCashCounponId(cashCouponId);
    }

    /**
     * @param exchangeCode
     * @param integrationChannelId
     * @param whether
     * @return
     */
    @Override
    public IntegrationCashCouponWallet findByExchangeCodeAndIntegrationChannelIdAndIsDelete(String exchangeCode, Long integrationChannelId, Whether whether) {
        return integrationCashWalletCouponRepository.findByExchangeCodeAndIntegrationChannelIdAndIsDelete(exchangeCode, integrationChannelId, whether);
    }

    @Override
    public IntegrationCashCouponWallet findTop1ByFaceValueAndIntegrationChannelIdAndIsDeleteAndExchangeNum(BigDecimal faceVal, Long integrationChannelId, Whether whether, long exchangeNum) {
        return integrationCashWalletCouponRepository.findTop1ByFaceValueAndIntegrationChannelIdAndIsDeleteAndExchangeNum(faceVal, integrationChannelId, whether, exchangeNum);
    }

    /**
     * 现金券领取完毕发消息
     * @param mallId
     * @param mallCashCouponId
     */
    @Override
    public void findCashCouponWalletPushReceiveOverMsg(Long mallId, Long mallCashCouponId) throws Exception {
        if(mallId==null || mallCashCouponId==null) {
            return;
        }
        MallCashCoupon mallCashCoupon = mallCashCouponRepository.findByIdAndMallId(mallCashCouponId,mallId);
        if(mallCashCoupon==null) {
            return;
        }
        Long quantity = mallCashCoupon.getQuantity();
        if(quantity==null) {
            return;
        }
        Long receiveNum = integrationCashWalletCouponRepository.queryCashWalletReceiveCount(mallId,mallCashCouponId);
        if(receiveNum==null) {
            return;
        }
        log.info("findCashCouponWalletPushReceiveOverMsg quantity:{},receiveNum:{}",quantity,receiveNum);
        if(quantity.longValue()==receiveNum.longValue()+1) {
            String constantContent = SysMessageConstants.M2M_MALL_CASH_COUPON_WALLET_RECEIVE_OVER.getContent();
            String content = MessageFormat.format(constantContent, mallCashCoupon.getName());
            SysMessageHelper.SINGLETON.pushOpMsg(SysMessageConstants.M2M_MALL_CASH_COUPON_WALLET_RECEIVE_OVER, content, mallId, null);
        }
    }

    /**
     * 现金券使用完毕发消息
     * @param mallId
     * @param mallCashCouponId
     */
    @Override
    public void findCashCouponWalletPushUseOverMsg(Long mallId, Long mallCashCouponId) throws Exception {
        if(mallId==null || mallCashCouponId==null) {
            return;
        }
        MallCashCoupon mallCashCoupon = mallCashCouponRepository.findByIdAndMallId(mallCashCouponId,mallId);
        if(mallCashCoupon==null) {
            return;
        }
        Long quantity = mallCashCoupon.getQuantity();
        if(quantity==null) {
            return;
        }
        Long useNum = integrationCashWalletCouponRepository.queryCashWalletUseCount(mallId,mallCashCouponId);
        if(useNum==null) {
            return;
        }
        log.info("findCashCouponWalletPushUseOverMsg quantity:{},receiveNum:{}",quantity,useNum);
        if(quantity.longValue()==useNum.longValue()+1) {
            String constantContent = SysMessageConstants.M2M_MALL_CASH_COUPON_WALLET_USE_OVER.getContent();
            String content = MessageFormat.format(constantContent, mallCashCoupon.getName());
            SysMessageHelper.SINGLETON.pushOpMsg(SysMessageConstants.M2M_MALL_CASH_COUPON_WALLET_USE_OVER, content, mallId, null);
        }
    }
}
